{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d1f20875-c50d-46df-906b-49ec1d0c6002",
   "metadata": {},
   "source": [
    "## 9.3 使用Sequential搭建神经网络实现手写数字识别\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c90a18b9-d8e8-431c-856c-35f1e4ed05e1",
   "metadata": {},
   "source": [
    "### 1.任务描述\n",
    "\n",
    "搭建神经网络，实现手写数字识别。\n",
    "\n",
    "要求：\n",
    "- 使用Sequential搭建神经网络\n",
    "- 神经网络为多层网络，包含1个隐含层和1个输出层\n",
    "- 输入层使用拉平层将特征数据拉平成一维数组\n",
    "- 隐含层有128个神经元\n",
    "- 输出层有10个神经元\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f5b4fc39-cbcf-432a-bf1e-e75e642d4b87",
   "metadata": {},
   "source": [
    "### 2.知识准备\n",
    "\n",
    "见教程。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c1d0295a-4ac4-470a-8263-027a3d69ac2c",
   "metadata": {},
   "source": [
    "### 3.任务分析\n",
    "\n",
    "网络的输入层可以使用Flatten方法来将其定义成拉平层，将输入的二维数据（28像素×28像素）拉平成长度为784像素的一维数据。\n",
    "\n",
    "隐含层则可以使用Dense方法来定义，并指定该层神经元的个数，以及该层所使用的激活函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "435c6090-cfda-4f46-a550-22a368e41e4a",
   "metadata": {},
   "source": [
    "### 4.任务实施\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec75eb6c-5da3-467d-a471-ca3b47242dd6",
   "metadata": {},
   "source": [
    "执行代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2ae9da58-e339-4d22-9f8d-ca255711d89e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "938/938 [==============================] - 3s 2ms/step - loss: 0.2994 - sparse_categorical_accuracy: 0.9144 - val_loss: 0.1576 - val_sparse_categorical_accuracy: 0.9533\n",
      "Epoch 2/10\n",
      "938/938 [==============================] - 2s 2ms/step - loss: 0.1344 - sparse_categorical_accuracy: 0.9608 - val_loss: 0.1105 - val_sparse_categorical_accuracy: 0.9669\n",
      "Epoch 3/10\n",
      "938/938 [==============================] - 2s 3ms/step - loss: 0.0928 - sparse_categorical_accuracy: 0.9727 - val_loss: 0.0904 - val_sparse_categorical_accuracy: 0.9730\n",
      "Epoch 4/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0706 - sparse_categorical_accuracy: 0.9788 - val_loss: 0.0835 - val_sparse_categorical_accuracy: 0.9744\n",
      "Epoch 5/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0552 - sparse_categorical_accuracy: 0.9834 - val_loss: 0.0863 - val_sparse_categorical_accuracy: 0.9739\n",
      "Epoch 6/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0456 - sparse_categorical_accuracy: 0.9869 - val_loss: 0.0799 - val_sparse_categorical_accuracy: 0.9754\n",
      "Epoch 7/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0360 - sparse_categorical_accuracy: 0.9891 - val_loss: 0.0728 - val_sparse_categorical_accuracy: 0.9765\n",
      "Epoch 8/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0298 - sparse_categorical_accuracy: 0.9911 - val_loss: 0.0721 - val_sparse_categorical_accuracy: 0.9790\n",
      "Epoch 9/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0238 - sparse_categorical_accuracy: 0.9935 - val_loss: 0.0731 - val_sparse_categorical_accuracy: 0.9792\n",
      "Epoch 10/10\n",
      "938/938 [==============================] - 3s 3ms/step - loss: 0.0202 - sparse_categorical_accuracy: 0.9943 - val_loss: 0.0740 - val_sparse_categorical_accuracy: 0.9787\n",
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " flatten (Flatten)           (None, 784)               0         \n",
      "                                                                 \n",
      " dense (Dense)               (None, 128)               100480    \n",
      "                                                                 \n",
      " dense_1 (Dense)             (None, 10)                1290      \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 101,770\n",
      "Trainable params: 101,770\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "# 1，导入包\n",
    "import tensorflow as tf\n",
    "\n",
    "# 2，准备数据集\n",
    "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()\n",
    "\n",
    "# 对输入特征进行归一化，使原本为0～255之间的值变成0～1之间的值\n",
    "x_train,x_test=x_train / 255.0, x_test / 255\n",
    "\n",
    "# 3，搭建网络\n",
    "model=tf.keras.models.Sequential([\n",
    "    # 使用拉平层，将输入特征变为一维数组\n",
    "    tf.keras.layers.Flatten(),\n",
    "    # 隐含层，128个神经元，使用ReLU激活函数\n",
    "    tf.keras.layers.Dense(128,activation='relu'),\n",
    "    # 输出层，10个神经元，使用Softmax激活函数使输出符合概率分布\n",
    "    tf.keras.layers.Dense(10,activation='softmax')\n",
    "])\n",
    "\n",
    "# 4，配置训练方法\n",
    "model.compile(\n",
    "    # 优化器选择Adam\n",
    "    optimizer='adam',\n",
    "    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits= False),\n",
    "    metrics=['sparse_categorical_accuracy']\n",
    ")\n",
    "\n",
    "# 5，执行训练过程\n",
    "model.fit(\n",
    "    x_train,\n",
    "    y_train,\n",
    "    batch_size=64,\n",
    "    epochs=10,\n",
    "    # 设置测试集\n",
    "    validation_data=(x_test, y_test), \n",
    "    # 验证频率，每迭代一次训练集，执行一次测试集的评测\n",
    "    validation_freq=1\n",
    ")\n",
    "\n",
    "# 6，打印网络结构和统计参数数据\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3b3e36e-8418-4caf-af51-d8ac80e2a321",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
